package com.lire.shop.controller;

import com.google.gson.Gson;
import com.lire.shop.converter.ChecklistConverter;
import com.lire.shop.dao.*;
import com.lire.shop.data.Constants;
import com.lire.shop.data.NullObjects;
import com.lire.shop.entity.*;
import com.lire.shop.model.vo.ChecklistVO;
import com.lire.shop.service.WalletService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Tag(name = "wallet")
@RestController
public class WalletController {

    @Autowired
    private Gson gson;
    @Autowired
    WalletRepository walletRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private WalletService walletService;

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private ChecklistRepository checklistRepository;

    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private ChecklistConverter checklistConverter;


    @PutMapping("/wallet/add/{money}")
    public String addMoney(@PathVariable String money, HttpSession session) {
        BigDecimal bdMoney = new BigDecimal(money);
        User curUser = (User) session.getAttribute("user");
        Long wid = curUser.getWid();
        Wallet wallet = walletRepository.findById(wid).get();
        BigDecimal balances = wallet.getBalances();

        BigDecimal newBalances = balances.add(bdMoney);
        wallet.setBalances(newBalances);

        walletRepository.save(wallet);
        return new Gson().toJson(wallet);
    }

    @Operation(summary = "查看账号余额", tags = {"wallet", "01-test"})
    @ApiResponses({
            @ApiResponse(responseCode = "200"
                    , content = {@Content(schema = @Schema(implementation = Checklist.class), mediaType = "application/json")})
    })
    @GetMapping("/wallet/balance")
    public String getBalance(HttpSession session) {
        User curUser = (User) session.getAttribute(Constants.CURRENT_USER);
        User user = userRepository.findByUsername(curUser.getUsername())
                .orElseGet(NullObjects::getUser);
        BigDecimal balances = walletService.getBalances(user.getWid());

        Map<String,Object> map = new HashMap<>();
        map.put("username",user.getUsername());
        map.put("balances",balances.toString());
        return gson.toJson(map);
    }

    @PatchMapping("/wallet/refund")
    public String refundMoney(String money, HttpSession session) {
        BigDecimal moneyBd = new BigDecimal(money);
        User curUser = (User) session.getAttribute(Constants.CURRENT_USER);
        User user = userRepository.findByUsername(curUser.getUsername())
                .orElseGet(NullObjects::getUser);
        Optional<Wallet> walletOptional = walletRepository.findById(user.getWid());
        Wallet wallet = walletOptional.orElseGet(NullObjects::getWallet);
        BigDecimal balances = wallet.getBalances();
        BigDecimal newBalances = balances.add(moneyBd);
        wallet.setBalances(newBalances);
        walletRepository.updateBalancesByWid(newBalances, wallet.getWid());
        return gson.toJson(wallet);
    }

    @PatchMapping("/wallet/spent")
    public String spentMoney(String money, HttpSession session) {
        BigDecimal moneyBd = new BigDecimal(money);
        User curUser = (User) session.getAttribute(Constants.CURRENT_USER);
        User user = userRepository.findByUsername(curUser.getUsername())
                .orElseGet(NullObjects::getUser);
        Optional<Wallet> walletOptional = walletRepository.findById(user.getWid());
        Wallet wallet = walletOptional.orElseGet(NullObjects::getWallet);
        BigDecimal balances = wallet.getBalances();
        if (balances.compareTo(moneyBd) > 0) {
            BigDecimal newBalances = balances.subtract(moneyBd);
            wallet.setBalances(newBalances);
            walletRepository.updateBalancesByWid(newBalances, wallet.getWid());
        }
        return gson.toJson(wallet);
    }

    @Operation(summary = "查看金额变动明细", tags = {"钱包管理", "01-test"})
    @ApiResponses({
            @ApiResponse(responseCode = "200"
                    , content = {@Content(schema = @Schema(implementation = Checklist.class)
                    , mediaType = "application/json")})})
    @GetMapping("/wallet/checklist")
    public String getChecklist(HttpSession session) {

        User curUser = (User) session.getAttribute(Constants.CURRENT_USER);
        User user = userRepository.findByUsername(curUser.getUsername())
                .orElseGet(NullObjects::getUser);
        List<Order> orders = orderRepository.findAllByUid(user.getUid());
        List<Long> oids = orders.stream().map(Order::getOid).collect(Collectors.toList());

        List<Checklist> checklists = checklistRepository.findAllByOid(oids)
                .stream()
                .sorted((c1,c2) -> c2.getCreateTime().compareTo(c1.getCreateTime()))
                .collect(Collectors.toList());
        Map<String, Object> map = new HashMap<>();
        if (checklists.isEmpty()) {
            map.put("msg", "无法获取信息");
            return gson.toJson(map);
        }

        List<ChecklistVO> checklistVOList = new ArrayList<>();
        for (Checklist checklist:checklists){
            Order order = orderRepository.findById(checklist.getOid()).orElseGet(NullObjects::getOrder);
            Product product = productRepository.findById(order.getPid()).orElseGet(NullObjects::getProduct);
            ChecklistVO checklistVO = checklistConverter.do2vo(checklist,order,product);
            checklistVOList.add(checklistVO);
        }
        map.put("checklists", checklistVOList);
        map.put("checklistsCount", checklists.size());
        return gson.toJson(map);
    }

}
